import json
import os
import logging
import time
from pprint import pprint
from urllib.parse import urljoin

# import pudb;pu.db
import copy
import moment
import requests
from pyquery import PyQuery as jq
from termcolor import colored
from retry import retry
logging.basicConfig(level=logging.INFO,
                    format='[%(asctime)s] >>> %(levelname)s  %(name)s: %(message)s')
PROXYURI = 'http://127.0.0.1:1087'
CHANELS = {}
MEDIA_PATH = 'EXCELS'


loger = logging.getLogger('YTB')
session = requests.Session()
session.timeout = 6
# session.proxies = {
#     'http': PROXYURI,
#     'https': PROXYURI,
# }
session.headers.update({
    "accept-language": "en;q=0.8",
    "cache-control": "max-age=0",
    "upgrade-insecure-requests": "1",
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
    "x-client-data": "CLK1yQEIl7bJAQimtskBCMG2yQEIqZ3KAQioo8oBGPmlygE="
})




# @retry()
def GetList():
    resp = session.get(
        'https://www.youtube.com/channel/UC4R8DWoMoI7CAwX8_LjQHig')
    res = list(filter(lambda item: 'ytInitialData' in item.text(),
                      jq(resp.text)('script').items()))
    resScript = json.loads(res[0].text().replace(
        'window["ytInitialData"] = ', '').split('window["ytInitialPlayerResponse"]')[0].strip()[:-1])
    SaveJson(resScript, 'resScript.json')
    for group in resScript['contents']['twoColumnBrowseResultsRenderer']['tabs'][0]['tabRenderer']['content']['sectionListRenderer']['contents']:
        group = group['itemSectionRenderer']['contents'][0]['shelfRenderer']
        SaveJson(group['content'],'content.json')
        for video in group['content']['horizontalListRenderer' if 'horizontalListRenderer' in group['content'] else 'expandedShelfContentsRenderer']['items']:
            video = video['gridVideoRenderer' if 'gridVideoRenderer' in video else 'videoRenderer']
            if 'badges' in video and video['badges'][0]['metadataBadgeRenderer']['style'] == 'BADGE_STYLE_TYPE_LIVE_NOW':
                TYPES = group['title']['runs'][0]['text'].split(' - ')[-1]
                VID = video['videoId']
                CHANELS[VID] = {
                    'type':TYPES,
                    'title': video['title']['simpleText'],
                    'thumb_link': video['thumbnail']['thumbnails'][0]['url'],
                    'href': urljoin(resp.url, video['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']),
                    'channel_link': urljoin(resp.url, video['shortBylineText']['runs'][0]['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']),
                    'channel_title': video['shortBylineText']['runs'][0]['text'],
                    'watching': int(video['viewCountText']['simpleText'].split()[0].replace(',', '')) if 'simpleText' in video['viewCountText'] else 0 ,
                    'live': True,
                    'datas': {}
                }
    loger.info(colored(f'GET LIVE NOW CHANNEL [{len(CHANELS.keys())}]','green'))

@retry()
def GetLiveChat(VID, continuation):
    url = f"https://www.youtube.com/live_chat/get_live_chat?continuation={continuation}&hidden=false&pbj=1"
    loger.info(colored(f'FETCH {url}','yellow'))
    headers = {
        "accept-language": "en;q=0.8",
        "cache-control": "no-cache",
        "pragma": "no-cache",
        "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36",
        "x-youtube-client-name": "1",
        "x-youtube-client-version": "2.20181010",
        "x-youtube-utc-offset": "480"
    }
    resp = session.get(url,  headers=headers)
    resp.encoding = 'utf8'
    datas = resp.json()
    SaveJson(datas,'get_live_chat.json')
    if "continuationContents" in datas['response']:
        for item in datas['response']['continuationContents']['liveChatContinuation'].get('actions',[]):
            if 'addChatItemAction' in item:
                render = item['addChatItemAction']['item'].get('liveChatTextMessageRenderer',None)
                if not render :
                    continue
                try:
                    if 'simpleText' in render['message']:
                        renderDatas = {
                            'message': render['message']['simpleText'],
                            'username': render['authorName']['simpleText'],
                            'datetime': moment.date(render['timestampUsec']).format('YYYY-MM-DD HH:mm:ss')
                        }
                        CHANELS[VID]['datas'][render['timestampUsec']] = renderDatas
                        loger.info(colored(
                            f'[{renderDatas["datetime"]}] {renderDatas["username"]}: {renderDatas["message"]}', 'blue'))
                        loger.info(colored(f'{VID}','magenta'))
                except Exception as e:
                    loger.error(colored(e,'red'))
                    loger.error(colored(render,'red'))
        return list(datas['response']['continuationContents']['liveChatContinuation']['continuations'][0].items())[0][1]['continuation']


# @retry()
def GetStartLiveChatID(vid):
    channel_link = f'https://www.youtube.com/live_chat?is_popout=1&v={vid}'
    loger.info(colored(f'FETCH {channel_link}', 'yellow'))
    resp = session.get(channel_link)
    resp.encoding = 'utf8'
    res = list(filter(lambda item: 'ytInitialData' in item.text(),
                      jq(resp.text)('script').items()))
    if not res:
        return ''
    else:
        resScript = json.loads(res[0].text().replace(
            'window["ytInitialData"] = ', '')[:-1])
        SaveJson(resScript,'frist_resScript.json')
        if "liveChatRenderer" in resScript['contents']:
            LiveChatID = list(resScript['contents']['liveChatRenderer']['continuations'][0].items())[0][1]['continuation']
            loger.info(colored(f'GET LIVECHATID: [{LiveChatID}]','green'))
            loger.info(colored(f'{vid}','cyan'))
            return LiveChatID
        elif "messageRenderer" in resScript['contents']:
            loger.info(colored(f'{vid}: {resScript["contents"]["messageRenderer"]["text"]["simpleText"]}','red'))


def SaveHTML(text, filename='res.html'):
    with open(filename, 'w') as f:
        f.write(text)
    


def SaveJson(datas, filename):
    filename = f"{MEDIA_PATH}/{filename}"
    with open(filename, 'w',encoding='utf8') as f:
        f.write(json.dumps(datas, indent=4, ensure_ascii=False))
    loger.info(colored(f'SAVED -> {filename}','green'))

def Sleep(delay):
    loger.info(colored(f'Sleeping ... Until {moment.date(str(int(time.time() + delay)))}','blue')) 
    time.sleep(delay)

# timestamp, user id, video id, video title, message id, message body, better to have video category, e.g. sports, news, animals, gaming

def main():    
    GetList()
    while True:
        for VID, item in copy.deepcopy(CHANELS).items():
            continuation = CHANELS[VID].get('continuation')
            try:
                CHANELS[VID]['continuation'] = GetLiveChat(VID, continuation) if continuation else GetStartLiveChatID(VID)
            except Exception as e:
                loger.error(colored(e,'red'))
        Sleep(5)
        
def initPath():
    PATHLIST = [MEDIA_PATH]
    for path in PATHLIST:
        if not os.path.exists(path):
            os.makedirs(path)


if __name__ == '__main__':
    try:
        initPath()
        start_time = moment.now().format("YYYYMMDD_HHmm")
        main()
    except KeyboardInterrupt:
        pass
    except Exception as e:
        loger.error(colored(e,'red'))
    finally:
        SaveJson(CHANELS, f'YTB-{start_time}-to-{moment.now().format("YYYYMMDD_HHmm")}.json')
